﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using Space.Library;
using Space.Library.Input;
using Space.Model.Data;
using Space.Model.Entity;

namespace Space.Model
{
    public class GameRunner
    {
        private static GameRunner _instance;

        public static GameRunner Instance
        {
            get
            {
                if (_instance == null)
                    _instance = new GameRunner();
                return _instance;
            }
        }

        public GameState GameState { get; set; }
        public Random Random = new Random();
        public Painter Painter { get; set; }
        public List<EntityBase> Entities { get; set; }

        public float Framerate { get; private set; }

        public IEnumerable<Ship> ShipEntities
        {
            get { return Entities.OfType<Ship>(); }
        }

        public Ship SelectedEntity { get; set; }

        private GameRunner()
        {
            _instance = this;

            Entities = new List<EntityBase>();
        }

        private long _currentTime = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
        private long _accumulator = 0;
        private long _t = 0;
        private const int _dt = 10; // Time step
        private int _frameRateUpdate = 0;

        public void Tick()
        {
            long newTime = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
            long frameTime = newTime - _currentTime;
            if (frameTime > 250)
                frameTime = 250;	  // note: max frame time to avoid spiral of death
            _currentTime = newTime;

            _accumulator += frameTime;

            while (_accumulator >= _dt)
            {
                // SAVE CURRENT STATE
                // previousState = currentState;
                foreach (var entity in Entities)
                {
                    entity.Tick(this, _dt);
                }

                _t += _dt;
                _accumulator -= _dt;
            }


            // TODO: Blend 
            //double alpha = (double)_accumulator / _dt;
            //State state = currentState * alpha + previousState * (1.0 - alpha);
            //render(state);


            InputManager.Instance.HandleInput();
            
            Painter.Paint(this);

            if (_frameRateUpdate++ == 10)
            {
                _frameRateUpdate = 0;
                Framerate = 1000f/frameTime;
            }
        }


        public void Init(GameRunner runner)
        {
            Board.Init();
            GameState = new GameState{CurrentTurnOwner = OwnerType.Player};
            Painter.Init();
            
            new DataLoader(this).LoadData();




            foreach (var entity in Entities)
            {
                entity.Init(this);
            }

        }

        public void Cleanup(GameRunner runner)
        {
            foreach (var entity in Entities)
            {
                entity.Cleanup(this);
            }
        }
    }
}
